import torch


def pca(X, num_components):
    # 标准化数据
    mean = torch.mean(X, dim=0)
    X_centered = X - mean

    # 计算协方差矩阵
    cov_matrix = torch.mm(X_centered.t(), X_centered) / (X.shape[0] - 1)

    # 特征值分解
    eigenvalues, eigenvectors = torch.linalg.eigh(cov_matrix)

    # 按特征值降序排列特征向量
    sorted_indices = torch.argsort(eigenvalues, descending=True)
    eigenvectors = eigenvectors[:, sorted_indices]

    # 选择前num_components个主成分
    principal_components = eigenvectors[:, :num_components]

    # 转换数据
    X_reduced = torch.mm(X_centered, principal_components)

    return X_reduced, principal_components


# 示例数据 (假设每行是一个样本，每列是一个特征)
X = torch.tensor([[2.5, 2.4, 3.3],
                  [0.5, 0.7, 1.9],
                  [2.2, 2.9, 3.1],
                  [1.9, 2.2, 2.6]])

# 选择降维后的特征数量
num_components = 2

# 运行PCA
X_reduced, components = pca(X, num_components)

print("降维后的数据:\n", X_reduced)
print("主成分:\n", components)
